package com.pangu.core.nettyserver.handler;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.annotation.OnConnect;
import com.corundumstudio.socketio.annotation.OnDisconnect;
import com.corundumstudio.socketio.annotation.OnEvent;
import com.pangu.core.BMDataContext;
import com.pangu.core.cache.CacheHelper;
import com.pangu.core.engine.game.ActionTaskUtils;
import com.pangu.core.engine.game.ChessGameEngine;
import com.pangu.core.engine.game.Message;
import com.pangu.core.engine.game.BeiMiGameEvent;
import com.pangu.core.engine.game.model.PlayerRecordHonghei;
import com.pangu.core.nettyserver.client.NettyClients;
import com.pangu.util.GameUtils;
import com.pangu.util.ProcessCard;
import com.pangu.util.disruptor.DisruptorHandler;
import com.pangu.util.rules.model.BetStatus;
import com.pangu.util.rules.model.BetVo;
import com.pangu.util.rules.model.Board;
import com.pangu.util.rules.model.GameStatus;
import com.pangu.util.rules.model.NiuniuBoard;
import com.pangu.util.rules.model.Player;
import com.pangu.util.rules.model.PokerBoard;
import com.pangu.util.rules.model.RedBlackStatus;
import com.pangu.util.rules.model.TopPlayer;
import com.pangu.util.rules.model.ZhajinhuaTakeCards;
import com.pangu.web.model.GameRoom;
import com.pangu.web.model.Notice;
import com.pangu.web.model.PlayUserClient;
import com.pangu.web.model.Token;
import com.pangu.web.service.NoticeService;
import com.pangu.web.service.repository.es.PlayUserClientESRepository;
import com.pangu.web.service.repository.jpa.PlayUserClientRepository;

import lombok.extern.slf4j.Slf4j;

/**
 * @ClassName: ChessEventHandler
 * @Description: 棋牌游戏公共事件处理器
 * @date 2018年3月24日 下午2:21:43
 *
 */
@Slf4j
public class ChessEventHandler {
	protected SocketIOServer server;

	@Autowired
	public ChessEventHandler(SocketIOServer server) {
		this.server = server;
	}

	/**
	 * 公用连接事件
	 */
	@OnConnect
	public void onConnect(SocketIOClient client) {
		log.info("Chess客户端已经连上·······································");
	}

	@OnEvent(value = "hello")
	public void hello(SocketIOClient client, String data) {
		System.out.println("data:" + data);
		client.sendEvent(BMDataContext.BEIMI_GAMESTATUS_EVENT, "hello!" + data);

	}

	@OnEvent(value = "hello1")
	public void hello1(SocketIOClient client, String data) {
		System.out.println("data:" + data);
		client.sendEvent(BMDataContext.BEIMI_GAMESTATUS_EVENT, "hello!" + data);

	}

	/**
	 * 
	 * Description:
	 * 用户登录以后进入大厅的时候前端发起请求把当前client放入缓存，不然的话没办法推送相关的消息，因为在发送推送的时候会判断client信息是否在缓存里面，这里实现简单工作，把client放入缓存
	 * 
	 * @author abo
	 * @date 2018年5月12日
	 * @param client
	 * @param data
	 */
	@OnEvent(value = "initdata")
	public void initData(SocketIOClient client, String data) {
		// socket客户端对象
		BeiMiClient beiMiClient = JSON.parseObject(data, BeiMiClient.class);
		String token = beiMiClient.getToken();
		Token userToken = (Token) CacheHelper.getApiUserCacheBean().getCacheObject(token, beiMiClient.getOrgi());
		JSONObject json = new JSONObject();
		json.put("command", "initdata");
		// 校验token 不为空
		if (beiMiClient == null || StringUtils.isBlank(token) || userToken == null) {
			json.put("status", -1);
			json.put("message", "用户的userId错误或userToken为空请重试");
		} else {
			// 缓存里面获取到玩家客户端，该客户端用户登陆的时候会创建
			PlayUserClient userClient = (PlayUserClient) CacheHelper.getApiUserCacheBean()
					.getCacheObject(userToken.getUserid(), userToken.getOrgi());
			beiMiClient.setClient(client);
			userClient.setStatus(BMDataContext.PlayerTypeEnum.NORMAL.toString());
			beiMiClient.setUserid(userClient.getId());
			beiMiClient.setSession(client.getSessionId().toString());// sessionId 每断开一次重新连接都是变化的。
			/**
			 * 心跳时间
			 */
			beiMiClient.setTime(System.currentTimeMillis());
			// 把客户端缓存到systemClientsMap 里面 主键是客户端ID
			NettyClients.getInstance().putClient(userClient.getId(), beiMiClient);
			json.put("status", 1);
			json.put("message", "initdata请求成功");
		}
		client.sendEvent("command", json);
	}

	/**
	 * @Description :权限过滤
	 * @author 老王
	 * 
	 */
	private BeiMiClient checkAuth(SocketIOClient client, String data) {
		// socket客户端对象
		BeiMiClient beiMiClient = JSON.parseObject(data, BeiMiClient.class);
		String token = beiMiClient.getToken();
		Token userToken;
		// 校验token 不为空
		if (beiMiClient == null || StringUtils.isBlank(token) || (userToken = (Token) CacheHelper.getApiUserCacheBean()
				.getCacheObject(token, beiMiClient.getOrgi())) == null) {
			BetStatus bs = new BetStatus();
			bs.setBetstatus(-1);
			bs.setMessage("无法获取客户端");
			client.sendEvent(bs.getCommand(), bs);
			return null;
		}
		beiMiClient.setUserid(userToken.getUserid());
		return beiMiClient;
	}

	/**
	 * @Description :权限校验
	 * @author 老王
	 */
	private Token checkAuth(SocketIOClient client) {
		BetStatus bs = new BetStatus();
		BeiMiClient beiMiClient = NettyClients.getInstance().getClient(client.getSessionId().toString());
		if (beiMiClient == null) {
			bs.setMessage("无法获取客户端");
			bs.setBetstatus(-1);
			client.sendEvent(bs.getCommand(), bs);
			return null;
		}
		String token = beiMiClient.getToken();
		if (StringUtils.isBlank(token)) {
			bs.setMessage("token为空");
			bs.setBetstatus(-1);
			client.sendEvent(bs.getCommand(), bs);
			return null;
		}
		Token userToken = (Token) CacheHelper.getApiUserCacheBean().getCacheObject(beiMiClient.getToken(),
				beiMiClient.getOrgi());
		return userToken;

	}

	/**
	 * 德州进入房间
	 */
	@OnEvent(value = "pokerJoinroom")
	public void pokerJoinroom(SocketIOClient client, AckRequest request, String data) {
		// 1.权限验证
		BeiMiClient beiMiClient = checkAuth(client, data);
		if (beiMiClient == null) {
			return;
		}
		PlayUserClient userClient = (PlayUserClient) CacheHelper.getApiUserCacheBean()
				.getCacheObject(beiMiClient.getUserid(), beiMiClient.getOrgi());
		// 开始游戏
		GameRoom gameRoom = BMDataContext.getPokerEngine().CreateGame(beiMiClient.getPlayway(), beiMiClient.getOrgi(),
				userClient);
		// 设置相关数据
		beiMiClient.setClient(client);
		userClient.setStatus(BMDataContext.PlayerTypeEnum.NORMAL.toString());
		beiMiClient.setUserid(userClient.getId());
		beiMiClient.setSession(client.getSessionId().toString());// sessionId 每断开一次重新连接都是变化的。
		beiMiClient.setTime(System.currentTimeMillis());
		NettyClients.getInstance().putClient(userClient.getId(), beiMiClient);
		userClient.setOnline(true);
		CacheHelper.getApiUserCacheBean().put(userClient.getId(), userClient, userClient.getOrgi());

		if (gameRoom != null) {
			JSONObject json = new JSONObject();
			json.put("command", "joinroom");
			json.put("status", 1);
			json.put("room", JSON.toJSON(gameRoom));
			json.put("game_seat", BMDataContext.getContext().getBean(ChessGameEngine.class)
					.getTopPlayer(gameRoom.getId(), gameRoom.getOrgi(), 9));
			json.put("message", "登录成功");
			// 发送给前端
			client.sendEvent("command", json);
		}

		// 获取牌局
		PokerBoard board = (PokerBoard) CacheHelper.getBoardCacheBean().getCacheObject(gameRoom.getId(),
				gameRoom.getOrgi());
		if (board != null) {
			board.setCommand(BMDataContext.BEIMI_GAME_LASTHANDS);
			BMDataContext.getPokerEngine().cleaningDate(board, beiMiClient.getUserid());
			client.sendEvent(board.getCommand(), board);
		}
		BMDataContext.getContext().getBean(ChessGameEngine.class).sendRecord(gameRoom,
				BMDataContext.GameTypeEnum.DEZHOU.toString());
	
		//@ FIXME  广播个人信息到所有用户
		userClient.setCommand(BMDataContext.BEIMI_PLAYERS_EVENT);
		ActionTaskUtils.sendEvent(userClient.getCommand(), userClient, gameRoom);
		

	}

	/*
	 * 加入房间,这是socket客户端连上来调用的第一个事件，会初始化一些数据。
	 */
	@OnEvent(value = "joinroom")
	public void onJoinRoom(SocketIOClient client, AckRequest request, String data) {
		BeiMiClient beiMiClient = checkAuth(client, data);
		if (beiMiClient == null) {
			return;
		}

		// 获取到房间数据，先从队列里面去取，然后去GameRoomCacheBean里面获取到实时的数据。
		GameRoom gameRoom = (GameRoom) CacheHelper.getQueneCache().get(beiMiClient.getPlayway(), beiMiClient.getOrgi());
		gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(gameRoom.getId(),
				beiMiClient.getOrgi());

		// 缓存里面获取到玩家客户端，该客户端用户登陆的时候会创建
		PlayUserClient userClient = (PlayUserClient) CacheHelper.getApiUserCacheBean()
				.getCacheObject(beiMiClient.getUserid(), beiMiClient.getOrgi());

		beiMiClient.setClient(client);
		userClient.setStatus(BMDataContext.PlayerTypeEnum.NORMAL.toString());
		beiMiClient.setUserid(userClient.getId());
		beiMiClient.setSession(client.getSessionId().toString());// sessionId 每断开一次重新连接都是变化的。
		/**
		 * 心跳时间
		 */
		beiMiClient.setTime(System.currentTimeMillis());
		// 把客户端缓存到systemClientsMap 里面 主键是客户端ID
		NettyClients.getInstance().putClient(userClient.getId(), beiMiClient);
		/**
		 * 你眼中的自己，有没有看起来的那么坚强。你的步伐，是否一如往昔的坚定。 更新当前玩家状态，在线|离线
		 */
		userClient.setOnline(true);
		userClient.setRoomid(gameRoom.getId());
		// 更新缓存
		CacheHelper.getApiUserCacheBean().put(userClient.getId(), userClient, userClient.getOrgi());

		List<PlayUserClient> playerList = CacheHelper.getGamePlayerCacheBean().getCacheObject(gameRoom.getId(),
				gameRoom.getOrgi());
		// 该数据存缓存里面，然后会在下注的时候，以及结算的时候推算数据，每一局开始的时候初始化数据
		BMDataContext.getNiuniuEngine().joinRoom(gameRoom, userClient, playerList);

		if (gameRoom != null) {
			JSONObject json = new JSONObject();
			json.put("command", "joinroom");
			json.put("status", 1);
			json.put("room", JSON.toJSON(gameRoom));
			json.put("game_seat", BMDataContext.getContext().getBean(ChessGameEngine.class)
					.getTopPlayer(gameRoom.getId(), gameRoom.getOrgi(), 6));
			json.put("message", "登录成功");
			// 发送给前端
			client.sendEvent("command", json);
			// json =
			// BMDataContext.getRedBlackGameEngine().getHistoryBoards(userClient.getRoomid(),
			// json);
			GameStatus statue = (GameStatus) CacheHelper.getGameStatusCacheBean().getCacheObject(gameRoom.getRoomid(),
					gameRoom.getOrgi());
			ActionTaskUtils.sendEvent(statue.getCommand(), statue);
		}
		// 获取牌局
		NiuniuBoard board = (NiuniuBoard) CacheHelper.getBoardCacheBean().getCacheObject(gameRoom.getId(),
				gameRoom.getOrgi());
		if (board != null) {
			board.setCommand(BMDataContext.BEIMI_GAME_LASTHANDS);
			client.sendEvent(BMDataContext.BEIMI_GAME_LASTHANDS, board);
		}
		BMDataContext.getContext().getBean(ChessGameEngine.class).sendRecord(gameRoom,
				BMDataContext.GameTypeEnum.NIUNIU.toString());
	}

	/*
	 * by:laowang 1。退出逻辑
	 */
	@OnEvent(value = "out")
	public void out(SocketIOClient client, String data) {
		BeiMiClient beiMiClient = NettyClients.getInstance().getClient(client.getSessionId().toString());

		if (beiMiClient == null) {
			return;
		}
		PlayUserClient playUserClient = (PlayUserClient) CacheHelper.getApiUserCacheBean()
				.getCacheObject(beiMiClient.getUserid(), beiMiClient.getOrgi());
		if (playUserClient == null) {
			return;
		}
		GameUtils.updatePlayerClientStatusForNiuniu(beiMiClient.getUserid(), beiMiClient.getOrgi(),
				BMDataContext.PlayerTypeEnum.LEAVE.toString());
		JSONObject json = new JSONObject();
		json.put("command", "out");
		json.put("status", 1);
		json.put("message", "退出成功");
		client.sendEvent("command", json);

	}

	/**
	 * @Description :德州Poker下注接口
	 * @author 老王
	 *         <p>
	 *         FIXME 对data的校验
	 */
	@OnEvent(value = "pokerbetting")
	public void pokerbetting(SocketIOClient client, String data) {
		Token userToken = checkAuth(client);
		if (userToken == null) {
			return;
		}
		BetVo betvo = JSON.parseObject(data, BetVo.class);
		String roomid = (String) CacheHelper.getRoomMappingCacheBean().getCacheObject(userToken.getUserid(), userToken.getOrgi());
		GameRoom gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(roomid, userToken.getOrgi());
		BMDataContext.getPokerEngine().betGameRequest(client, userToken.getUserid(),gameRoom,
				betvo.getCoin(),betvo.getSeat(), BMDataContext.PlayerTypeEnum.NORMAL.toString());
		GameUtils.getGame(gameRoom.getPlayway(), gameRoom.getOrgi()).change(gameRoom, BeiMiGameEvent.AUTO.toString());
	}

	/**
	 * @Description :betting(牛牛下注)
	 * @author 老王
	 *         <p>
	 *         FIXME 对data的校验
	 */
	@OnEvent(value = "betting")
	public void betting(SocketIOClient client, String data) {

		Token userToken = checkAuth(client);
		if (userToken == null) {
			return;
		}

		BetVo betvo = JSON.parseObject(data, BetVo.class);
		if (betvo == null || betvo.getSeat() < 1 || betvo.getSeat() > 4 || betvo.getCoin() == 0) {
			BetStatus bs = new BetStatus();
			bs.setMessage("参数错误");
			bs.setBetstatus(-1);
			client.sendEvent(bs.getCommand(), bs);
			return;
		}
		BMDataContext.getNiuniuEngine().betGameRequest(client, userToken, betvo.getSeat(), betvo.getCoin());
	}

	/**
	 * @Description :获取排行数据接口，传入roomId
	 * @author 老王
	 *         <p>
	 *         FIXME 对data的校验
	 */
	@OnEvent(value = "getRanking")
	public void getRanking(SocketIOClient client, String data) {
		BeiMiClient beiMiClient = checkAuth(client, data);
		if (beiMiClient == null) {
			return;
		}
		// 获取到房间数据，先从队列里面去取，然后去GameRoomCacheBean里面获取到实时的数据。
		GameRoom gameRoom = (GameRoom) CacheHelper.getQueneCache().get(beiMiClient.getPlayway(), beiMiClient.getOrgi());
		// 发送toper数据到前端
		BMDataContext.getContext().getBean(ChessGameEngine.class).sendTopPlayer(client, gameRoom.getId(),
				gameRoom.getOrgi(), 100);
	}

	/**
	 * 获取排行数据接口，传入roomId
	 */
	@OnEvent(value = "getSeat")
	public void getSeat(SocketIOClient client, String data) {
		log.info("获取排行数据·······································");
		BeiMiClient beiMiClient = NettyClients.getInstance().getClient(client.getSessionId().toString());
		if (beiMiClient == null) {
			return;
		}
		PlayUserClient playUserClient = (PlayUserClient) CacheHelper.getApiUserCacheBean()
				.getCacheObject(beiMiClient.getUserid(), beiMiClient.getOrgi());
		if (playUserClient == null) {
			return;
		}
		// 获取到房间数据，先从队列里面去取，然后去GameRoomCacheBean里面获取到实时的数据。
		GameRoom gameRoom = (GameRoom) CacheHelper.getQueneCache().get(beiMiClient.getPlayway(), beiMiClient.getOrgi());
		// 发送toper数据到前端
		BMDataContext.getContext().getBean(ChessGameEngine.class).sendTopPlayer(client, gameRoom.getId(),
				gameRoom.getOrgi(), 6);
	}

	// 添加@OnDisconnect事件，客户端断开连接时调用，刷新客户端信息
	@OnDisconnect
	public void onDisconnect(SocketIOClient client) {
		log.info("客户端已经断开·······································");
		BeiMiClient beiMiClient = NettyClients.getInstance().getClient(client.getSessionId().toString());
		if (beiMiClient == null) {
			return;
		}
		PlayUserClient playUserClient = (PlayUserClient) CacheHelper.getApiUserCacheBean()
				.getCacheObject(beiMiClient.getUserid(), beiMiClient.getOrgi());
		if (playUserClient == null) {
			return;
		}
		if (BMDataContext.GameStatusEnum.PLAYING.toString().equals(playUserClient.getGamestatus())) {// 在玩的状态
			GameUtils.updatePlayerClientStatusForNiuniu(beiMiClient.getUserid(), beiMiClient.getOrgi(),
					BMDataContext.PlayerTypeEnum.OFFLINE.toString());
		} else {
			CacheHelper.getGamePlayerCacheBean().delete(playUserClient.getId(), playUserClient.getOrgi());
			CacheHelper.getRoomMappingCacheBean().delete(playUserClient.getId(), playUserClient.getOrgi());
		}
	}

	/**
	 * 
	 * Description: 选择玩法
	 * 
	 * @author abo
	 * @date 2018年3月24日
	 * @param client
	 * @param request
	 * @param data
	 */
	@OnEvent(value = "selectplayway")
	public void onSelectPlayway(SocketIOClient client, String data) {
		BeiMiClient beiMiClient = JSON.parseObject(data, BeiMiClient.class);
		String token = beiMiClient.getToken();
		if (!StringUtils.isBlank(token)) {
			/**
			 * Token不为空，并且，验证Token有效，验证完毕即开始进行游戏撮合，房卡类型的 1、大厅房间处理 a、从房间队列里获取最近一条房间信息
			 * b、将token对应玩家加入到房间 c、如果房间凑齐了玩家，则将房间从等待撮合队列中移除，放置到游戏中的房间信息，如果未凑齐玩家，继续扔到队列
			 * d、通知房间的所有人，有新玩家加入 e、超时处理，增加AI进入房价 f、事件驱动 g、定时器处理 2、房卡房间处理 a、创建房间 b、加入到等待中队列
			 */
			Token userToken;
			if (beiMiClient != null && !StringUtils.isBlank(token) && (userToken = (Token) CacheHelper
					.getApiUserCacheBean().getCacheObject(token, beiMiClient.getOrgi())) != null) {
				// 鉴权完毕
				PlayUserClient userClient = (PlayUserClient) CacheHelper.getApiUserCacheBean()
						.getCacheObject(userToken.getUserid(), userToken.getOrgi());
				beiMiClient.setClient(client);
				beiMiClient.setUserid(userClient.getId());
				beiMiClient.setSession(client.getSessionId().toString());
				/**
				 * 心跳时间
				 */
				beiMiClient.setTime(System.currentTimeMillis());
				// 把客户端缓存到systemClientsMap 里面
				NettyClients.getInstance().putClient(userClient.getId(), beiMiClient);

				/**
				 * 更新当前玩家状态，在线|离线
				 */
				userClient.setOnline(true);

				// 更玩家新状态普通玩家，并且缓存玩家，并且清掉玩家之前的房间
				ActionTaskUtils.updatePlayerClientStatus(userClient, BMDataContext.PlayerTypeEnum.NORMAL.toString());

				// 持久化相关数据
				DisruptorHandler.published(userClient,
						BMDataContext.getContext().getBean(PlayUserClientESRepository.class),
						BMDataContext.getContext().getBean(PlayUserClientRepository.class));

				// 执行游戏相关业务
				// BMDataContext.getGameEngine().gameRequest(userToken.getUserid(),
				// beiMiClient.getPlayway(),
				// beiMiClient.getRoom(), beiMiClient.getOrgi(), userClient, beiMiClient);
				// 自定义引擎
				BMDataContext.getSangongGameEngine().gameRequest(userToken.getUserid(), beiMiClient.getPlayway(),
						beiMiClient.getRoom(), beiMiClient.getOrgi(), userClient, beiMiClient);
				System.out.println("selectPlayway socket方法执行完毕——————————————————————————————");
			}
		}
	}

	/**
	 * 
	 * Description: 开始游戏
	 * 
	 * @author abo
	 * @date 2018年3月26日
	 * @param client
	 * @param data
	 */
	@OnEvent(value = "startgame")
	public void onStartGame(SocketIOClient client, String data) {
		BeiMiClient beiMiClient = NettyClients.getInstance().getClient(client.getSessionId().toString());
		String token = beiMiClient.getToken();
		if (!StringUtils.isBlank(token)) {
			Token userToken = (Token) CacheHelper.getApiUserCacheBean().getCacheObject(token,
					BMDataContext.SYSTEM_ORGI);
			if (userToken != null) {

				PlayUserClient playUser = (PlayUserClient) CacheHelper.getGamePlayerCacheBean()
						.getPlayer(userToken.getUserid(), userToken.getOrgi());
				if (playUser != null) {
					BMDataContext.getGameEngine().startGameRequest(playUser.getRoomid(), playUser, userToken.getOrgi(),
							"true".equals(data));
				}
			}
		}
	}

	/**
	 * 
	 * Description: 事实更新房间状态
	 * 
	 * @author abo
	 * @date 2018年4月7日
	 * @param client
	 * @param request
	 * @param data
	 */
	@OnEvent(value = "redblackroomstatus")
	public void onRedBlackRoomStatus(SocketIOClient client, AckRequest request, String data) {
		RedBlackStatus redBlackStatus = BMDataContext.getRedBlackGameEngine().synRedBlackRoomStatus();
		client.sendEvent("command", redBlackStatus);
	}

	/**
	 * 
	 * Description: 红黑下注
	 * 
	 * @author abo
	 * @date 2018年4月5日
	 * @param client
	 * @param request
	 * @param data
	 */
	@OnEvent(value = "redblackbet")
	public void onRedBlackBet(SocketIOClient client, AckRequest request, String data) {
		// socket客户端对象
		BeiMiClient beiMiClient = JSON.parseObject(data, BeiMiClient.class);
		String token = beiMiClient.getToken();
		Token userToken;
		BetStatus betStatus = new BetStatus();// 投注状态
		betStatus.setCommand("bet");
		GameRoom gameRoom = null;
		// 校验token 不为空
		if (beiMiClient == null || StringUtils.isBlank(token) || (userToken = (Token) CacheHelper.getApiUserCacheBean()
				.getCacheObject(token, beiMiClient.getOrgi())) == null) {
			betStatus.setBetstatus(-1);
			betStatus.setMessage("token为空或者未获取成功");
		} else {
			// 缓存里面获取到玩家客户端，该客户端用户登陆的时候会创建
			PlayUserClient userClient = (PlayUserClient) CacheHelper.getApiUserCacheBean()
					.getCacheObject(userToken.getUserid(), userToken.getOrgi());
			// beiMiClient.setClient(client);
			// beiMiClient.setUserid(userClient.getId());
			// beiMiClient.setSession(client.getSessionId().toString());// sessionId
			// 每断开一次重新连接都是变化的。
			//
			// gameRoom = CacheHelper.getQueneCache().get(beiMiClient.getPlayway(),
			// beiMiClient.getOrgi());
			gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(userClient.getRoomid(),
					beiMiClient.getOrgi());
			// 获取前台的投注信息
			Map<String, String> map = beiMiClient.getExtparams();
			String betType = map.get("bettype");
			String betCoin = map.get("betcoin");

			if (userClient.getGoldcoins() < Integer.parseInt(betCoin)) {
				betStatus.setBetstatus(-1);
				betStatus.setMessage("下注金额大于用户余额");
			} else {
				// 先去缓存取此轮有没有下注
				List<PlayerRecordHonghei> prList = (List<PlayerRecordHonghei>) CacheHelper
						.getGameRecordHongheiCacheBean().getCacheObject(userClient.getId(), userClient.getOrgi());
				if (prList == null) {
					prList = new ArrayList<PlayerRecordHonghei>();
				}
				// 下注内容
				PlayerRecordHonghei pr = new PlayerRecordHonghei();
				pr.setRoomId(gameRoom.getId());
				pr.setOrgi("beimi");
				pr.setGameType(map.get("gametype"));
				pr.setGameTime(new Date());
				pr.setGameSubType(betType);
				pr.setPlayerId(userClient.getId());
				pr.setCoin(Double.parseDouble(betCoin));
				pr.setIsBanker("1");// 0庄，1闲
				pr.setPlayerType("1");
				prList.add(pr);
				// 下注以后把下注内容放到缓存，等会去结算
				CacheHelper.getGameRecordHongheiCacheBean().put(userClient.getId(), prList, userClient.getOrgi());
				betStatus.setBetstatus(1);
				betStatus.setBetCoin(Integer.parseInt(betCoin));
				betStatus.setBetType(betType);
				betStatus.setMessage("下注成功");
				betStatus.setUserid(userClient.getId());
			}
		}
		if (betStatus.getBetstatus() == 1) {
			// 如果下注成功就通知房间所有的人
			ActionTaskUtils.sendEvent("bet", betStatus, gameRoom);
		} else {
			client.sendEvent("command", betStatus);
		}
	}

	/**
	 * 
	 * Description: 加入房间,这是socket客户端连上来调用的第一个事件，会初始化一些数据。
	 * 
	 * @author abo
	 * @date 2018年4月5日
	 * @param client
	 * @param request
	 * @param data
	 */
	@OnEvent(value = "redblackjoinroom")
	public void onRedBlackJoinRoom(SocketIOClient client, AckRequest request, String data) {
		// 把页面传过来的值封装成beimiclient对象
		BeiMiClient beiMiClient = JSON.parseObject(data, BeiMiClient.class);
		String token = beiMiClient.getToken();
		Token userToken = (Token) CacheHelper.getApiUserCacheBean().getCacheObject(token, beiMiClient.getOrgi());
		// 校验token 不为空
		if (beiMiClient == null || StringUtils.isBlank(token) || userToken == null) {
			return;
		}
		// 缓存里面获取到玩家客户端，该客户端用户登陆的时候会创建
		PlayUserClient userClient = (PlayUserClient) CacheHelper.getApiUserCacheBean()
				.getCacheObject(userToken.getUserid(), userToken.getOrgi());
		beiMiClient.setClient(client);
		beiMiClient.setUserid(userClient.getId());
		beiMiClient.setSession(client.getSessionId().toString());// sessionId 每断开一次重新连接都是变化的。
		/**
		 * 心跳时间
		 */
		beiMiClient.setTime(System.currentTimeMillis());
		// 把客户端缓存到systemClientsMap 里面 主键是客户端ID
		NettyClients.getInstance().putClient(userClient.getId(), beiMiClient);
		/**
		 * 更新当前玩家状态，在线|离线
		 */
		userClient.setOnline(true);

		// 更玩家新状态
		ActionTaskUtils.updatePlayerClientStatus(userClient, BMDataContext.PlayerTypeEnum.NORMAL.toString());
		// 持久化相关数据
		DisruptorHandler.published(userClient, BMDataContext.getContext().getBean(PlayUserClientESRepository.class),
				BMDataContext.getContext().getBean(PlayUserClientRepository.class));

		// 执行游戏相关业务，加入房并且通知前端已经加入房间
		GameRoom room = CacheHelper.getQueneCache().get(beiMiClient.getPlayway(), beiMiClient.getOrgi());
		room = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(room.getId(), beiMiClient.getOrgi());
		BMDataContext.getRedBlackGameEngine().gameRequest(userToken.getUserid(), beiMiClient.getPlayway(), room,
				room.getOrgi(), userClient, beiMiClient);
	}

	/**
	 * 
	 * Description: 请求开牌信息
	 * 
	 * @author abo
	 * @date 2018年4月7日
	 * @param client
	 * @param request
	 * @param data
	 */
	@OnEvent(value = "redblackopencards")
	public void onRedBlackOpenCards(SocketIOClient client, AckRequest request, String data) {
		BeiMiClient beiMiClient = JSON.parseObject(data, BeiMiClient.class);
		String token = beiMiClient.getToken();
		Token userToken = (Token) CacheHelper.getApiUserCacheBean().getCacheObject(token, beiMiClient.getOrgi());
		JSONObject json = new JSONObject();
		json.put("command", "opencards");
		// 校验token 不为空
		if (beiMiClient == null || StringUtils.isBlank(token) || userToken == null) {
			json.put("status", -1);
			json.put("message", "token为空或错误，请求开牌失败");
		} else {
			PlayUserClient userClient = (PlayUserClient) CacheHelper.getApiUserCacheBean()
					.getCacheObject(userToken.getUserid(), userToken.getOrgi());
			Board board = (Board) CacheHelper.getBoardCacheBean().getCacheObject(userClient.getRoomid(),
					BMDataContext.SYSTEM_ORGI);

			Map<String, Object> map = ProcessCard.whoIsWinner(board);// 红胜还是黑胜
			json.put("cards", map);
			json.put("status", 1);
			json.put("message", "请求开牌成功");
		}
		client.sendEvent("command", json);
	}

	/**
	 * 
	 * Description: 请求红黑大战用户排行
	 * 
	 * @author abo
	 * @date 2018年4月7日
	 * @param client
	 * @param request
	 * @param data
	 */
	@OnEvent(value = "redblacktopplayers")
	public void onRedBlackTopPlayers(SocketIOClient client, AckRequest request, String data) {
		BeiMiClient beiMiClient = JSON.parseObject(data, BeiMiClient.class);
		// socket客户端对象
		String token = beiMiClient.getToken();
		Token userToken;
		BetStatus betStatus = new BetStatus();// 投注状态
		betStatus.setCommand("bet");
		// 校验token 不为空
		if (beiMiClient == null || StringUtils.isBlank(token) || (userToken = (Token) CacheHelper.getApiUserCacheBean()
				.getCacheObject(token, beiMiClient.getOrgi())) == null) {
		} else {
			PlayUserClient userClient = (PlayUserClient) CacheHelper.getApiUserCacheBean()
					.getCacheObject(userToken.getUserid(), userToken.getOrgi());
			// 执行游戏相关业务，加入房并且通知前端已经加入房间
			GameRoom gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(userClient.getRoomid(),
					beiMiClient.getOrgi());
			TopPlayer topPlayer = (TopPlayer) CacheHelper.getGamePlayerTopCacheBean().getCacheObject(gameRoom.getId(),
					gameRoom.getOrgi());
			if (topPlayer != null) {
				ActionTaskUtils.sendEvent(BMDataContext.BEIMI_GAME_TOP, topPlayer, gameRoom);
			}
		}
	}

	/**
	 * 
	 * Description: 请求红黑大战用户排行
	 * 
	 * @author abo
	 * @date 2018年4月7日
	 * @param client
	 * @param request
	 * @param data
	 */
	@OnEvent(value = "redblackquitroom")
	public void onRedBlackQuitRoom(SocketIOClient client, AckRequest request, String data) {
		BeiMiClient beiMiClient = JSON.parseObject(data, BeiMiClient.class);
		String token = beiMiClient.getToken();
		Token userToken;
		JSONObject json = new JSONObject();
		json.put("command", "quitroom");
		userToken = (Token) CacheHelper.getApiUserCacheBean().getCacheObject(token, beiMiClient.getOrgi());
		// 校验token 不为空
		if (beiMiClient == null || StringUtils.isBlank(token) || userToken == null) {
			json.put("quitstatus", -1);
			json.put("message", "token为空或错误，退出房间失败");
		} else {
			PlayUserClient userClient = (PlayUserClient) CacheHelper.getApiUserCacheBean()
					.getCacheObject(userToken.getUserid(), userToken.getOrgi());
			GameUtils.updatePlayerClientStatusForNiuniu(userClient.getId(), userClient.getOrgi(),
					BMDataContext.PlayerTypeEnum.LEAVE.toString());
			json.put("quitstatus", 1);
			json.put("message", "退出成功");
		}
		client.sendEvent("command", json);
	}

	/**
	 * 
	 * Description: 炸金花加入房间，初始化新房间，并且加入ai，发牌，准备开局
	 * 
	 * @author abo
	 * @date 2018年4月17日
	 * @param client
	 * @param request
	 * @param data
	 */
	@OnEvent(value = "zhajinhuajoinroom")
	public void onZhajinhuaJoinRoom(SocketIOClient client, AckRequest request, String data) {
		BeiMiClient beiMiClient = JSON.parseObject(data, BeiMiClient.class);
		String token = beiMiClient.getToken();
		if (!StringUtils.isBlank(token)) {
			Token userToken = (Token) CacheHelper.getApiUserCacheBean().getCacheObject(token, beiMiClient.getOrgi());
			if (beiMiClient != null && !StringUtils.isBlank(token) && userToken != null) {
				// 鉴权完毕
				PlayUserClient userClient = (PlayUserClient) CacheHelper.getApiUserCacheBean()
						.getCacheObject(userToken.getUserid(), userToken.getOrgi());
				beiMiClient.setClient(client);
				beiMiClient.setUserid(userClient.getId());
				beiMiClient.setSession(client.getSessionId().toString());
				// 心跳时间
				beiMiClient.setTime(System.currentTimeMillis());
				// 把客户端缓存到systemClientsMap 里面
				NettyClients.getInstance().putClient(userClient.getId(), beiMiClient);

				// 更新当前玩家状态，在线|离线
				userClient.setOnline(true);
				userClient.setRoomready(true);

				// 更玩家新状态，第一次进来的时候没有做什么事情
				ActionTaskUtils.updatePlayerClientStatus(userClient, BMDataContext.PlayerTypeEnum.NORMAL.toString());
				// 持久化相关数据
				DisruptorHandler.published(userClient,
						BMDataContext.getContext().getBean(PlayUserClientESRepository.class),
						BMDataContext.getContext().getBean(PlayUserClientRepository.class));
				// 执行游戏相关业务
				BMDataContext.getZhajinhuaEngine().gameRequest(userToken.getUserid(), beiMiClient.getPlayway(),
						beiMiClient.getRoom(), beiMiClient.getOrgi(), userClient, beiMiClient);
			}
		}
	}

	/**
	 * 
	 * Description: 发起查看牌的指令
	 * 
	 * @author abo
	 * @date 2018年4月17日
	 * @param client
	 * @param data
	 */
	@OnEvent(value = "zhajinhualookcard")
	public void onZhajinhuaLookCard(SocketIOClient client, String data) {
		BeiMiClient beiMiClient = NettyClients.getInstance().getClient(client.getSessionId().toString());
		String token = beiMiClient.getToken();
		JSONObject json = new JSONObject();
		json.put("command", "lookcard");
		if (!StringUtils.isBlank(token)) {
			Token userToken = (Token) CacheHelper.getApiUserCacheBean().getCacheObject(token,
					BMDataContext.SYSTEM_ORGI);
			if (userToken != null) {
				PlayUserClient playUser = (PlayUserClient) CacheHelper.getApiUserCacheBean()
						.getCacheObject(userToken.getUserid(), userToken.getOrgi());
				String roomid = (String) CacheHelper.getRoomMappingCacheBean().getCacheObject(playUser.getId(),
						playUser.getOrgi());
				// 取到当前房间的牌局信息，发牌信息在牌局里面
				Board board = (Board) CacheHelper.getBoardCacheBean().getCacheObject(roomid, playUser.getOrgi());
				Player[] players = board.getPlayers();
				Player player = null;
				// 获取当前请求看牌的player
				for (int i = 0; i < players.length; i++) {
					if (players[i].getPlayuser().equals(playUser.getId())) {
						player = players[i];
						player.setDocatch(true);// 设置为看牌状态
					}
				}
				board.setPlayers(players);
				// 重新放进去
				CacheHelper.getBoardCacheBean().put(roomid, board, playUser.getOrgi());
				json.put("cards", ProcessCard.openJinhuaCards(player.getCards()));
				json.put("status", 1);
				json.put("message", "请求成功");
			}
		} else {
			json.put("status", -1);
			json.put("message", "token错误请重试");
		}
		// log.info(json.toJSONString());
		client.sendEvent("command", json);
	}

	/**
	 * 
	 * Description: 发起比牌指令
	 * 
	 * @author abo
	 * @date 2018年4月17日
	 * @param client
	 * @param data
	 */
	@OnEvent(value = "zhajinhuacomparecard")
	public void onZhajinhuaCompareCard(SocketIOClient client, String data) {
		BeiMiClient beiMiClient = JSON.parseObject(data, BeiMiClient.class);
		// 获取前台的投注信息
		Map<String, String> map = beiMiClient.getExtparams();
		String anotherPlayerId = map.get("anotherPlayer");// 比牌的对象玩家
		JSONObject json = new JSONObject();
		json.put("command", "comparecard");
		if (!StringUtils.isBlank(anotherPlayerId)) {
			String token = beiMiClient.getToken();
			if (!StringUtils.isBlank(token)) {
				Token userToken = (Token) CacheHelper.getApiUserCacheBean().getCacheObject(token,
						BMDataContext.SYSTEM_ORGI);
				if (userToken != null) {
					PlayUserClient playUser = (PlayUserClient) CacheHelper.getApiUserCacheBean()
							.getCacheObject(userToken.getUserid(), userToken.getOrgi());
					String roomid = (String) CacheHelper.getRoomMappingCacheBean().getCacheObject(playUser.getId(),
							playUser.getOrgi());
					// 取到当前房间的牌局信息，发牌信息在牌局里面
					Board board = (Board) CacheHelper.getBoardCacheBean().getCacheObject(roomid, playUser.getOrgi());
					json = BMDataContext.getZhajinhuaEngine().execCompareCard(playUser, board, json, map);
					int currentPlayerNum = Integer.parseInt(json.get("currentPlayerNum").toString());
					// 存活并且未弃牌人数大于1游戏继续，未弃牌人数小于2前台发起结算
					if (currentPlayerNum > 1) {
						log.info("--------------------------------------" + playUser.getId() + "比牌打断记时");
						// 激活注册机到下一步
						BMDataContext.getZhajinhuaEngine().takeCardsRequest(roomid,
								board.getNextplayer().getNextplayer(), playUser.getOrgi(), true, null);
					} else {
						GameRoom gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(roomid,
								beiMiClient.getOrgi());
						// 进入下一步结算 激活注册机到下一步
						GameUtils.getGame(gameRoom.getPlayway(), gameRoom.getOrgi()).change(gameRoom,
								BeiMiGameEvent.ALLCARDS.toString()); // 通知状态机
					}
				}
			} else {
				json.put("status", -1);
				json.put("message", "token错误请重试");
			}
		} else {
			json.put("status", -1);
			json.put("message", "未获取到比牌玩家");
		}
		client.sendEvent("command", json);
	}

	/**
	 * 
	 * Description: 弃牌，如果只有2人了，一人弃牌那么需要传出结算标志，如果弃牌后未弃牌的人数大于2人，牌局继续
	 * 
	 * @author abo
	 * @date 2018年4月17日
	 * @param client
	 * @param data
	 */
	@OnEvent(value = "zhajinhuagiveupcard")
	public void onZhajinhuaGiveUpCard(SocketIOClient client, String data) {
		BeiMiClient beiMiClient = JSON.parseObject(data, BeiMiClient.class);
		JSONObject json = new JSONObject();
		json.put("command", "giveup");
		String token = beiMiClient.getToken();
		ZhajinhuaTakeCards zhajinhuaTakeCards = new ZhajinhuaTakeCards();
		if (!StringUtils.isBlank(token)) {
			Token userToken = (Token) CacheHelper.getApiUserCacheBean().getCacheObject(token,
					BMDataContext.SYSTEM_ORGI);
			if (userToken != null) {
				PlayUserClient playUser = (PlayUserClient) CacheHelper.getApiUserCacheBean()
						.getCacheObject(userToken.getUserid(), userToken.getOrgi());
				String roomId = (String) CacheHelper.getRoomMappingCacheBean().getCacheObject(playUser.getId(),
						playUser.getOrgi());

				zhajinhuaTakeCards = BMDataContext.getZhajinhuaEngine().execGiveup(playUser, roomId,
						zhajinhuaTakeCards);
				zhajinhuaTakeCards.setUserid(playUser.getId());
				zhajinhuaTakeCards.setActionType(3);
				zhajinhuaTakeCards.setRoomId(roomId);
			}
		} else {
			json.put("status", -1);
			json.put("message", "token错误请重试");
		}
		GameRoom gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(zhajinhuaTakeCards.getRoomId(),
				beiMiClient.getOrgi());
		ActionTaskUtils.sendEvent("zhajinhuatakecards", zhajinhuaTakeCards, gameRoom);

	}

	/**
	 * 
	 * Description: 下注，金额为0就是跟注，金额大于0就是加注
	 * 
	 * @author abo
	 * @date 2018年4月17日
	 * @param client
	 * @param data
	 */
	@OnEvent(value = "zhajinhuabet")
	public void onZhajinhuaBet(SocketIOClient client, String data) {
		// socket客户端对象
		BeiMiClient beiMiClient = JSON.parseObject(data, BeiMiClient.class);
		String token = beiMiClient.getToken();
		Token userToken;
		BetStatus betStatus = new BetStatus();// 投注状态
		betStatus.setCommand("bet");
		ZhajinhuaTakeCards zhajinhuaTakeCards = new ZhajinhuaTakeCards();
		// 校验token 不为空
		if (beiMiClient == null || StringUtils.isBlank(token) || (userToken = (Token) CacheHelper.getApiUserCacheBean()
				.getCacheObject(token, beiMiClient.getOrgi())) == null) {
			betStatus.setBetstatus(-1);
			betStatus.setMessage("token为空或者未获取成功");
		} else {
			// 缓存里面获取到玩家客户端，该客户端用户登陆的时候会创建
			PlayUserClient userClient = (PlayUserClient) CacheHelper.getApiUserCacheBean()
					.getCacheObject(userToken.getUserid(), userToken.getOrgi());
			String roomid = (String) CacheHelper.getRoomMappingCacheBean().getCacheObject(userToken.getUserid(),
					userToken.getOrgi());
			GameRoom room = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(roomid, beiMiClient.getOrgi());
			// 获取前台的投注信息
			Map<String, String> map = beiMiClient.getExtparams();
			String betCoin = map.get("betcoin");
			if (userClient.getGoldcoins() < Integer.parseInt(betCoin)) {
				betStatus.setBetstatus(-1);
				betStatus.setMessage("下注金额大于用户余额");
			} else {
				betStatus = BMDataContext.getZhajinhuaEngine().execBet(userClient, room, betStatus, map);
				zhajinhuaTakeCards.setUserid(userClient.getId());
				zhajinhuaTakeCards.setBetCoin(Double.parseDouble(betCoin));
				ActionTaskUtils.sendEvent("zhajinhuatakecards", zhajinhuaTakeCards, room);
				Board board = (Board) CacheHelper.getBoardCacheBean().getCacheObject(room.getId(), room.getOrgi());
				System.out
						.println("--------------------------------------" + zhajinhuaTakeCards.getUserid() + "下注打断记时");
				// 激活注册机到下一步
				BMDataContext.getZhajinhuaEngine().takeCardsRequest(room.getId(), board.getNextplayer().getNextplayer(),
						userClient.getOrgi(), true, null);
			}
		}
	}

	/**
	 * 
	 * Description: 获取历史公告
	 * 
	 * @author abo
	 * @date 2018年5月11日
	 * @param client
	 * @param data
	 */
	@OnEvent(value = "gethistorynotice")
	public void onGetHistoryNotice(SocketIOClient client, String data) {
		BeiMiClient beiMiClient = JSON.parseObject(data, BeiMiClient.class);
		JSONObject json = new JSONObject();
		json.put("command", "gethistorynotice");
		String token = beiMiClient.getToken();
		Token userToken = (Token) CacheHelper.getApiUserCacheBean().getCacheObject(token, beiMiClient.getOrgi());
		// 判断用户是否为空
		if (!StringUtils.isBlank(token) && userToken != null) {
			NoticeService messageService = BMDataContext.getContext().getBean(NoticeService.class);
			Notice notice = new Notice();
			notice.setUserid(userToken.getUserid());
			Sort sort = new Sort(Direction.DESC, "createtime");
			List<Notice> page = messageService.getNoticeListByUserId(notice, sort);
			json.put("noticelist", page);
			json.put("status", 1);
			json.put("message", "请求成功");
		} else {
			json.put("status", -1);
			json.put("message", "用户的userId错误请重试");
		}
		client.sendEvent("command", json);
	}

	/**
	 * 
	 * Description: 请求红黑大战历史记录
	 * 
	 * @author abo
	 * @date 2018年4月7日
	 * @param client
	 * @param request
	 * @param data
	 */
	@OnEvent(value = "redblackhistoryboard")
	public void onRedBlackHistoryBoard(SocketIOClient client, AckRequest request, String data) {
		BeiMiClient beiMiClient = JSON.parseObject(data, BeiMiClient.class);
		String token = beiMiClient.getToken();
		Token userToken;
		JSONObject json = new JSONObject();
		json.put("command", "redblackhistoryboard");
		userToken = (Token) CacheHelper.getApiUserCacheBean().getCacheObject(token, beiMiClient.getOrgi());
		// 校验token 不为空
		if (beiMiClient == null || StringUtils.isBlank(token) || userToken == null) {
			json.put("status", -1);
			json.put("message", "token为空或错误，请求红黑大战历史记录失败");
		} else {
			PlayUserClient userClient = (PlayUserClient) CacheHelper.getApiUserCacheBean()
					.getCacheObject(userToken.getUserid(), userToken.getOrgi());
			log.info("userClient.getRoomid():{}", userClient.getRoomid());
			json = BMDataContext.getRedBlackGameEngine().getHistoryBoards(userClient.getRoomid(), json);
			log.info("历史记录:{}", JSON.toJSON(json));
			json.put("status", 1);
			json.put("message", "请求红黑大战历史记录成功");
		}
		client.sendEvent("command", json);
	}
}